package io.bdmc.modules.bss.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import io.bdmc.common.utils.ByteUtil;
import io.bdmc.common.utils.R;
import io.bdmc.core.msp2000.DataBuild;
import io.bdmc.core.msp2000.DataParse;
import io.bdmc.core.msp2000.Msp2000ThreadPool;
import io.bdmc.core.msp2000.SetMsgResponse;
import io.bdmc.core.msp2000.model.*;
import io.bdmc.core.udp.UdpClientSendData;
import io.bdmc.modules.bss.entity.*;
import io.bdmc.modules.bss.model.AlarmDataType;
import io.bdmc.modules.bss.service.*;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;

// "设置设备参数", description = "/bss/device/set")
@RestController
@RequestMapping("/bss/device/set")
public class DeviceSettingController {

    @Autowired
    IDeviceDeviceService _deviceService;

    @Autowired
    UdpClientSendData _udpClient;

    @Autowired
    IDeviceMachineFanService _fanService;

    @Autowired
    IDeviceMachineEdfaService _edfaService;

    @Autowired
    IDeviceMachineFecService _fecService;

    @Autowired
    IDeviceMachineFecModuleService _fecModuleService;

    @Autowired
    IDeviceMachinePowerService _powerService;

    @Autowired
    IDeviceMachineRtService _rtService;

    @Autowired
    IDeviceMachineFspService _fspService;

    @Autowired
    IDeviceMachineRfaService _rfaService;

    @Autowired
    Msp2000ThreadPool _msp2000Svs;

    /**
     * 下发风扇配置信息
     * 
     * @param setFan 风扇配置
     * @return R
     */
    // "下发风扇配置信息", notes = "下发风扇配置信息")
    @PostMapping("fan")
    public R setFan(@RequestBody SetFan setFan) {
        DeviceDevice parentDevice = _deviceService.selectParentDeviceBySn(setFan.getSn());
        DeviceDevice currentDevice = _deviceService.getDeviceBySn(setFan.getSn());
        if (parentDevice == null || currentDevice == null)
            return R.error();
        List<DeviceMachineFan> deviceMachineFanList = _fanService.selectLastFanData(setFan.getSn());
        String str = DataBuild.buildSetFanMsg(setFan);
        String parseData = _udpClient.sendPollCommand(parentDevice.getIpaddr(), parentDevice.getDevicePort(), str);
        Msp2000Ter2Platform msg = DataParse.parseAllMsg(ByteUtil.hexToBytes(parseData));
        boolean result = DataParse.parseResponseData(msg.getData());
        String message = "";
        String beforeValue = "";
        String afterValue = "";
        if (result) {
            // final DeviceMachineFan deviceMachineFan ;
            Optional<DeviceMachineFan> deviceMachineFan = deviceMachineFanList.stream()
                    .filter(r -> r.getFanNum() == setFan.getFanNum()).findFirst();
            if (deviceMachineFan.isPresent()) {
                switch (setFan.getMask()) {
                    case 1:
                        message = "设置风扇模式";
                        beforeValue = deviceMachineFan.get().getFanMode().toString();
                        afterValue = setFan.getFanMode() + "";
                        break;
                    case 2:
                        message = "设置风扇转速";
                        beforeValue = deviceMachineFan.get().getFanRpm().toString();
                        afterValue = setFan.getFanRpm() + "";
                        break;
                    case 3:
                        message = "设置风扇模式+转速";
                        beforeValue = deviceMachineFan.get().getFanMode().toString() + ","
                                + deviceMachineFan.get().getFanRpm().toString();
                        afterValue = setFan.getFanMode() + "," + setFan.getFanRpm() + "";
                        break;
                    default:
                        break;
                }
                saveAlarmEvent(currentDevice.getDeptId(),currentDevice.getDeviceSn(), currentDevice.getDeviceId(), message, beforeValue,
                        afterValue);
            }
            _msp2000Svs.sendPollCommandMSP2000();
        }
        return R.trueOrFalse(result);
    }

    /**
     * 下发EDFA配置信息
     * 
     * @param edfaSetting EDFA配置信息
     * @return R
     */
    // "下发EDFA配置信息", notes = "下发EDFA配置信息")
    @PostMapping("edfa")
    public R setEdfa(@RequestBody EdfaSetting edfaSetting) {
        DeviceDevice parentDevice = _deviceService.selectParentDeviceBySn(edfaSetting.getSn());
        DeviceDevice currentDevice = _deviceService.getDeviceBySn(edfaSetting.getSn());
        if (parentDevice == null || currentDevice == null)
            return R.error();
        DeviceMachineEdfa deviceMachineEdfa = _edfaService.selectLastEdfaData(edfaSetting.getSn());

        String hexStr = DataBuild.buildSetEDFA(edfaSetting);
        String parseData = _udpClient.sendPollCommand(parentDevice.getIpaddr(), parentDevice.getDevicePort(), hexStr);
        if(io.bdmc.common.utils.StringUtils.isEmpty(parseData)){
            return R.error("设备暂无响应，请确认连接状态。");
        }
        Msp2000Ter2Platform msg = DataParse.parseAllMsg(ByteUtil.hexToBytes(parseData));
        boolean result = DataParse.parseResponseData(msg.getData());
        String message = "";
        String beforeValue = "";
        String afterValue = "";
        if (result && deviceMachineEdfa != null) {
            switch (edfaSetting.getMask()) {
                case 1:
                    message = "设置输入门限";
                    beforeValue = deviceMachineEdfa.getInputLightlessAlarmThreshold();
                    afterValue = edfaSetting.getInputThreshold() + "";
                    break;
                case 2:
                    message = "设置输出门限";
                    // beforeValue = deviceMachineEdfa.getOutputAlarmGate();
                    // afterValue = edfaSetting.getOutputThreshold()+"";
                    break;
                case 4:
                    message = "设置增益值";
                    beforeValue = deviceMachineEdfa.getApcPowerSetting();
                    afterValue = edfaSetting.getGainValue() + "";
                    break;
                case 8:
                case 24:
                    message = "设置工作状态";
                    beforeValue = getWorkStatusLabel(deviceMachineEdfa.getWorkStatus());
                    afterValue = getWorkStatusLabel(edfaSetting.getWorkStatus());
                    break;
                default:
                    break;
            }
            saveAlarmEvent(currentDevice.getDeptId(),currentDevice.getDeviceSn(), currentDevice.getDeviceId(), message, beforeValue, afterValue);
            _msp2000Svs.sendPollCommandMSP2000();
        }
        return R.trueOrFalse(result);
    }

    @PostMapping("rfa")
    public R setRfa(@RequestBody EdfaSetting rfaSetting) {
        DeviceDevice parentDevice = _deviceService.selectParentDeviceBySn(rfaSetting.getSn());
        DeviceDevice currentDevice = _deviceService.getDeviceBySn(rfaSetting.getSn());
        if (parentDevice == null || currentDevice == null)
            return R.error();
        DeviceMachineRfa deviceMachineRfa = _rfaService.selectLastRfaData(rfaSetting.getSn());

        String hexStr = DataBuild.buildSetRFA1( rfaSetting.getSn(), rfaSetting.getMask(), rfaSetting.getInputThreshold(),
                rfaSetting.getOutputThreshold(), rfaSetting.getGainValue(), rfaSetting.getWorkStatus());
        String parseData = _udpClient.sendPollCommand(parentDevice.getIpaddr(), parentDevice.getDevicePort(), hexStr);
        if(io.bdmc.common.utils.StringUtils.isEmpty(parseData)){
            return R.error("设备暂无响应，请确认连接状态。");
        }
        Msp2000Ter2Platform msg = DataParse.parseAllMsg(ByteUtil.hexToBytes(parseData));
        boolean result = DataParse.parseResponseData(msg.getData());
        String message = "";
        String beforeValue = "";
        String afterValue = "";
        if (result && deviceMachineRfa != null) {
            switch (rfaSetting.getMask()) {
                case 1:
                    message = "设置输入门限";
                    beforeValue = deviceMachineRfa.getInputLightlessAlarmThreshold();
                    afterValue = rfaSetting.getInputThreshold() + "";
                    break;
                case 4:
                    message = "设置增益值";
                    beforeValue = deviceMachineRfa.getInputSignalPower();
                    afterValue = rfaSetting.getGainValue() + "";
                    break;
                case 24:
                    message = "设置工作状态";
                    beforeValue = getWorkStatusLabel(deviceMachineRfa.getWorkState());
                    afterValue = getWorkStatusLabel(rfaSetting.getWorkStatus());
                    break;
                default:
                    break;
            }
            saveAlarmEvent(currentDevice.getDeptId(),currentDevice.getDeviceSn(), currentDevice.getDeviceId(), message, beforeValue, afterValue);
            _msp2000Svs.sendPollCommandMSP2000();
        }
        return R.trueOrFalse(result);
    }

    String getWorkStatusLabel(String workStatus) {
        String str = "";
        switch (workStatus) {
            case "11":
            case "10":
                str = "无光关泵";
                break;
            case "01":
                str = "强制关泵";
                break;
            case "00":
                str = "无光不关泵";
                break;
            default:
                break;
        }
        return str;
    }

    /**
     * 下发RT配置信息
     *
     * @param rtSetting RT配置信息
     * @return R
     */
    // "下发RT配置信息", notes = "下发RT配置信息")
    @PostMapping("rt")
    public R setRT(@RequestBody EdfaSetting rtSetting) {
        DeviceDevice parentDevice = _deviceService.selectParentDeviceBySn(rtSetting.getSn());
        DeviceDevice currentDevice = _deviceService.getDeviceBySn(rtSetting.getSn());
        if (parentDevice == null || currentDevice == null)
            return R.error();
        DeviceMachineRt rt = _rtService.selectLastRtData(rtSetting.getSn());
        String hexStr = DataBuild.buildSetEDFA(rtSetting);
        String parseData = _udpClient.sendPollCommand(parentDevice.getIpaddr(), parentDevice.getDevicePort(), hexStr);
        if(io.bdmc.common.utils.StringUtils.isEmpty(parseData)){
            return R.error("设备暂无响应，请确认连接状态。");
        }
        Msp2000Ter2Platform msg = DataParse.parseAllMsg(ByteUtil.hexToBytes(parseData));
        boolean result = DataParse.parseResponseData(msg.getData());
        String message = "";
        String beforeValue = "";
        String afterValue = "";
        if (result && rt != null) {
            switch (rtSetting.getMask()) {
                case 1:
                    message = "设置输入门限";
                    beforeValue = rt.getInputLightlessAlarmThreshold();
                    afterValue = rtSetting.getInputThreshold() + "";
                    break;
                case 4:
                    message = "设置增益值";
                    beforeValue = rt.getApcPowerSetting();
                    afterValue = rtSetting.getGainValue() + "";
                    break;
                 case 24:
                    message = "设置工作状态";
                    beforeValue = getWorkStatusLabel(rt.getWorkStatus());
                    afterValue = getWorkStatusLabel(rtSetting.getWorkStatus());
                default:
                    break;
            }
            saveAlarmEvent(currentDevice.getDeptId(),currentDevice.getDeviceSn(), currentDevice.getDeviceId(), message, beforeValue, afterValue);
        }
        if (result)
            _msp2000Svs.sendPollCommandMSP2000();
        return R.trueOrFalse(result);
    }

    /**
     * 下发FSP配置信息
     * 
     * @param fsp FSP
     * @return R
     */
    // "下发FSP配置信息", notes = "下发FSP配置信息")
    @PostMapping("fsp")
    public R setFsp(@RequestBody DeviceMachineFsp fsp) {
        DeviceMachineFsp dbFsp = _fspService.getById(fsp.getMachineFspId());
        if(fsp.getWorkMode().equals("70")||fsp.getWorkMode().equals("80")){
            if(!dbFsp.getWorkMode().equals("50")&&!dbFsp.getWorkMode().equals("60")){
                return R.error("请先修改工作模式为手动");
            }
        }

        DeviceDevice parentDevice = _deviceService.selectParentDeviceBySn(fsp.getDiskSn());
        DeviceDevice currentDevice = _deviceService.getDeviceBySn(fsp.getDiskSn());
        if (parentDevice == null || currentDevice == null)
            return R.error("设备异常");
        String fspMsg = DataBuild.buildSetFSPMsg(1, fsp);
        String parseData = _udpClient.sendPollCommand(parentDevice.getIpaddr(), parentDevice.getDevicePort(), fspMsg);
        if (StringUtils.isEmpty(parseData)) {
            return R.error("设备暂无响应，请确定电源是否已开启");
        }
        Msp2000Ter2Platform msg = DataParse.parseAllMsg(ByteUtil.hexToBytes(parseData));
        DeviceMachineFsp deviceMachineFsp = _fspService.selectLastFspData(fsp.getDiskSn());
        boolean result = DataParse.parseResponseData(msg.getData());
        if (result && deviceMachineFsp != null) {
            if (fsp.getWorkMode().equals("70") || fsp.getWorkMode().equals("80")) {
                String afterValue = "";
                if (fsp.getWorkMode().equals("70")) {
                    afterValue = "主发主收";
                } else {
                    afterValue = "备发备收";
                }
                saveAlarmEvent(currentDevice.getDeptId(),currentDevice.getDeviceSn(), currentDevice.getDeviceId(), "工作信道改变",
                        deviceMachineFsp.getWorkingChannel(), afterValue);
            } else {
                if (!fsp.getWorkMode().equals(deviceMachineFsp.getWorkMode())) {
                    saveAlarmEvent(currentDevice.getDeptId(),currentDevice.getDeviceSn(), currentDevice.getDeviceId(), "工作模式改变",
                            deviceMachineFsp.getWorkingChannel(), getWorkChannelStr(fsp.getWorkMode()));
                }
                if (!fsp.getLineType().equals(deviceMachineFsp.getLineType())) {
                    saveAlarmEvent(currentDevice.getDeptId(),currentDevice.getDeviceSn(), currentDevice.getDeviceId(), "工作线路类型改变",
                            getLineTypeStr(deviceMachineFsp.getLineType()), getLineTypeStr(fsp.getLineType()));
                }
            }
        }
        if (result)
            _msp2000Svs.sendPollCommandMSP2000();
        return R.trueOrFalse(result);
    }

    String getWorkChannelStr(String val) {
        String str = "";
        switch (val) {
            case "30":
                str = "自动不返回";
                break;
            case "40":
                str = "自动返回";
                break;
            case "50":
                str = "手动";
                break;
            case "60":
                str = "强制";
                break;
            default:
                break;
        }
        return str;
    }

    String getLineTypeStr(String val) {
        String str = "";
        switch (val) {
            case "15":
                str = "点对点、点对点";
                break;
            case "14":
                str = "点对点、含中继";
                break;
            case "17":
                str = "点对点、含光放";
                break;
            case "11":
                str = "含中继、点对点";
                break;
            case "10":
                str = "含中继、含中继";
                break;
            case "13":
                str = "含中继、含光放";
                break;
            case "1D":
                str = "含光放、点对点";
                break;
            case "1C":
                str = "含光放、含中继";
                break;
            case "1F":
                str = "含光放、含光放";
                break;
            default:
                break;
        }
        return str;
    }

    /**
     * fec设置模块的无光关断模式 或认证模式
     * 
     * @param lightMode 设置参数
     * @return R
     */
    // "下发模块的无光关断模式", notes = "下发模块的无光关断模式")
    @PostMapping("light")
    public R lightMode(@RequestBody LightModeSetting lightMode) {
        DeviceDevice parentDevice = _deviceService.selectParentDeviceBySn(lightMode.getSn());
        DeviceDevice currentDevice = _deviceService.getDeviceBySn(lightMode.getSn());
        if (parentDevice == null || currentDevice == null)
            return R.error();
        String send = DataBuild.buildSetNoLightOffMode(lightMode.getType(), lightMode.getSlotNum(), lightMode.getSn(),
                lightMode.getUchAddr(), lightMode.getMode());

        DeviceMachineFec fec = _fecService.selectLastFecData(lightMode.getSn());
        String moduleName = lightMode.getUchAddr() == 0 ? "模块1" : "模块2";
        DeviceMachineFecModule fecModule = _fecModuleService.getOne(new QueryWrapper<DeviceMachineFecModule>()
                .eq("machine_fec_id", fec.getMachineFecId()).eq("module_name", moduleName).last("LIMIT 1"));

        String parseData = _udpClient.sendPollCommand(parentDevice.getIpaddr(), parentDevice.getDevicePort(), send);
        Msp2000Ter2Platform msg = DataParse.parseAllMsg(ByteUtil.hexToBytes(parseData));
        SetMsgResponse setMsgResponse = DataParse.parseSetResponse(msg.getData());
        boolean result = setMsgResponse.isLightModeOK();
        if (result) {
            if (lightMode.getType().equals("21") && fecModule != null) {
                saveAlarmEvent(currentDevice.getDeptId(),currentDevice.getDeviceSn(), currentDevice.getDeviceId(), "设置激光器模式",
                        getLaserMode(Integer.parseInt(fecModule.getLaserMode())), getLaserMode(lightMode.getMode()));
            }

            _msp2000Svs.sendPollCommandMSP2000();
        }
        return R.trueOrFalse(result);
    }

    // "FEC参数设置", notes = "FEC参数设置")
    @PostMapping("fec")
    public R lightMode(@RequestBody FecSetting fecSetting) {
        DeviceDevice parentDevice = _deviceService.selectParentDeviceBySn(fecSetting.getSn());
        DeviceDevice currentDevice = _deviceService.getDeviceBySn(fecSetting.getSn());
        if (parentDevice == null || currentDevice == null)
            return R.error();
        String send = DataBuild.buildSetFECPara(fecSetting);

        DeviceMachineFec fec = _fecService.selectLastFecData(fecSetting.getSn());

        String parseData = _udpClient.sendPollCommand(parentDevice.getIpaddr(), parentDevice.getDevicePort(), send);
        Msp2000Ter2Platform msg = DataParse.parseAllMsg(ByteUtil.hexToBytes(parseData));
        SetMsgResponse setMsgResponse = DataParse.parseSetResponse(msg.getData());
        boolean result = setMsgResponse.isFecSetOK();
        if (result) {
            switch (fecSetting.getOptType()) {
                case 1:
                    saveAlarmEvent(currentDevice.getDeptId(),currentDevice.getDeviceSn(), currentDevice.getDeviceId(), "设置FEC模式",
                            getSpeedCodeStr(fec.getSpeedCodeClient()), getSpeedCodeStr(fecSetting.getSetVal()));
                    break;
                case 2:
                    saveAlarmEvent(currentDevice.getDeptId(),currentDevice.getDeviceSn(), currentDevice.getDeviceId(), "设置单板硬件芯片软件自环",
                            getFecLoopStatus(fec.getSpeedCodeClient()), getFecLoopStatus(fecSetting.getSetVal()));
                case 3:
                    saveAlarmEvent(currentDevice.getDeptId(),currentDevice.getDeviceSn(), currentDevice.getDeviceId(), "设置误码清零", "",
                            getWrongCodeStr(fecSetting.getSetVal()));
                case 4:
                    saveAlarmEvent(currentDevice.getDeptId(),currentDevice.getDeviceSn(), currentDevice.getDeviceId(), "设置FEC增益",
                            getFecPowerStr(fec.getSpeedCodeClient()), getFecPowerStr(fecSetting.getSetVal()));
                default:
                    break;
            }
            // 先记录日志，再刷新数据
            _msp2000Svs.sendPollCommandMSP2000();
        }
        return R.trueOrFalse(result);
    }

    private void saveAlarmEvent(int deptId,String deviceSn, int deviceId, String alarmMsg, String beforeValue, String afterValue) {
        LocalDateTime now = LocalDateTime.now();
        DeviceAlarmRealtime alarmRealtime = new DeviceAlarmRealtime();
        alarmRealtime.setDeviceId(deviceId);
        alarmRealtime.setDeviceSn(deviceSn);
        alarmRealtime.setDeptId(deptId);
        alarmRealtime.setDataType(AlarmDataType.EVENT.name());
        alarmRealtime.setAlarmMsg(alarmMsg);
        alarmRealtime.setMonitorValue1(beforeValue);
        alarmRealtime.setMonitorValue2(afterValue);
        alarmRealtime.setProcessed(false);
        alarmRealtime.setStartTime(now);
        alarmRealtime.setCreateTime(now);
        alarmRealtime.insert();
    }

    String getLaserMode(int intVal) {
        // int intVal = Integer.parseInt(val);
        String str = "";
        switch (intVal) {
            case 0:
                str = "无光关断";
                break;
            case 10:
                str = "无光不关断";
                break;
            case 1:
                str = "强制关断";
                break;
            default:
                break;
        }
        return str;
    }

    String getSpeedCodeStr(String codeStr) {
        String str = "";
        int code = Integer.parseInt(codeStr);
        switch (code) {
            case 21:
                str = "622M _CLK_SDH";
                break;
            case 20:
                str = "2.5G_CLK_SDH";
                break;
            case 7:
                str = "10G_CLK_OTU2F";
                break;
            case 6:
                str = "10G_CLK_OTU2E";
                break;
            case 5:
                str = "10G_CLK_OTU1E";
                break;
            case 4:
                str = "10G_CLK_OTU2";
                break;
            case 3:
                str = "10G_CLK_FC";
                break;
            case 2:
                str = "10G_CLK_LAN";
                break;
            case 1:
                str = "10G_CLK_SDH";
                break;
            case 0:
                str = "10G_CLK_NONE";
                break;
            case 23:
                str = "2.5G_CLK_OTU1";
                break;
            case 22:
                str = "155M _CLK_SDH";
                break;
            default:
                break;
        }
        return str;
    }

    String getWrongCodeStr(String setVal) {
        int intVal = Integer.parseInt(setVal);
        String str = "";
        switch (intVal) {
            case 0:
                str = "当前误码清零";
                break;
            case 1:
                str = "历史误码清零";
                break;
            case 2:
                str = "全部误码清零";
                break;
            default:
                break;
        }
        return str;
    }

    String getFecPowerStr(String setVal) {
        int intVal = Integer.parseInt(setVal);
        String str = "";
        switch (intVal) {
            case 0:
                str = "eFECI4";
                break;
            case 1:
                str = "eFECI7";
                break;
            case 2:
                str = "G.709 - RSFEC";
                break;
            case 3:
                str = "FEC type Swizzle 100G";
            default:
                break;
        }
        return str;
    }

    String getFecLoopStatus(String setVal) {
        int intVal = Integer.parseInt(setVal);
        String str = "";
        switch (intVal) {
            case 176:
                str = "客户侧外环回关闭";
                break;
            case 112:
                str = "客户侧内环回关闭";
                break;
            case 208:
                str = "线路测内环回关闭";
                break;
            case 210:
                str = "线路测内环回开启";
                break;
            case 225:
                str = "线路测外环回开启";
                break;
            case 120:
                str = "客户侧内环回开启";
                break;
            case 180:
                str = "客户侧外环回开启";
                break;
            default:
                break;
        }
        return str;
    }
}
